package com.iwhalecloud.bss.kite.cucc.order.util;

import com.github.pagehelper.PageInfo;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.iwhalecloud.bss.kite.client.api.cust.query.IQueryAccountService;
import com.iwhalecloud.bss.kite.client.dto.cust.AccountDTO;
import com.iwhalecloud.bss.kite.client.dto.shoppingcart.ShoppingCartItemFeeDTO;
import com.iwhalecloud.bss.kite.client.enums.AccountSearchType;
import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.constant.SwitchConsts;
import com.iwhalecloud.bss.kite.common.constant.TableConsts;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.cucc.order.loader.InstLoaderFactory;
import com.iwhalecloud.bss.kite.dataservice.entity.AcctItemHis;
import com.iwhalecloud.bss.kite.dataservice.entity.OrderItem;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferInst;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferObjInstRel;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferResInstRelExt;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.ProdInst;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.ProdInstFunc;
import com.iwhalecloud.bss.kite.dataservice.entity.order.OrderItemChange;
import com.iwhalecloud.bss.kite.dataservice.mapper.inst.ProdInstMapper;
import com.iwhalecloud.bss.kite.dataservice.util.GeneralSwitchUtils;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInst;
import com.iwhalecloud.bss.kite.manager.util.ManagerUtils;
import com.iwhalecloud.bss.kite.order.client.dto.InstContainer;
import com.iwhalecloud.bss.kite.order.client.dto.OrderContainer;
import com.iwhalecloud.bss.kite.order.client.dto.OrderRequest;
import com.ztesoft.bss.base.staticdata.CoreDataOffer;
import com.ztesoft.bss.common.exception.BssException;
import com.ztesoft.bss.common.util.SpringUtil;
import com.ztesoft.bss.order.base.consts.KeyValues;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

/**
 * @author v
 * @since 2020/2/27
 */
public abstract class OrderFeeUtil {

    private static Map<InstType, String> instTypeCartItemCdMapping = ImmutableMap.<InstType, String>builder()
        .put(InstType.PROD_INST_ACCT, KeyConsts.SHOPPING_CART_ITEM_CD_ZH)
        .put(InstType.GIFT_OFFER_INST, KeyConsts.SHOPPING_CART_ITEM_CD_XSP)
        .put(InstType.MAIN_OFFER_INST, KeyConsts.SHOPPING_CART_ITEM_CD_XSP)
        .put(InstType.PROMOTION_OFFER_INST, KeyConsts.SHOPPING_CART_ITEM_CD_XSP)
        .put(InstType.ADDITIONAL_OFFER_INST, KeyConsts.SHOPPING_CART_ITEM_CD_XSP)
        .put(InstType.PROD_INST, KeyConsts.SHOPPING_CART_ITEM_CD_CP)
        .put(InstType.PROD_INST_FUNC, KeyConsts.SHOPPING_CART_ITEM_CD_GNCP)
        .put(InstType.MKT_RES_INST, KeyConsts.SHOPPING_CART_ITEM_CD_YXZY)
        .build();

    private static Map<String, InstType> offerType2InstType = ImmutableMap.<String, InstType>builder()
        .put(KeyConsts.OFFER_TYPE_10, InstType.PROD_INST)
        .put(KeyConsts.OFFER_TYPE_11, InstType.MAIN_OFFER_INST)
        .put(KeyConsts.OFFER_TYPE_12, InstType.ADDITIONAL_OFFER_INST)
        .put(KeyConsts.OFFER_TYPE_13, InstType.PROMOTION_OFFER_INST)
        .put(KeyConsts.OFFER_TYPE_15, InstType.GIFT_OFFER_INST)
        .build();

    private static Map<String, InstType> tableNameInstTypeMappinst = ImmutableMap.<String, InstType>builder()
        .put(TableConsts.ProdInst.getTableName(), InstType.PROD_INST)
        .put(TableConsts.ProdInstFunc.getTableName(), InstType.PROD_INST_FUNC)
        .put(TableConsts.OfferResInstRelExt.getTableName(), InstType.MKT_RES_INST)
        .put(TableConsts.ProdInstAcctRel.getTableName(), InstType.PROD_INST_ACCT)
        .put(TableConsts.OfferInstAssureExt.getTableName(), InstType.OFFER_INST_ASSURE)
        .put(TableConsts.ProdInstState.getTableName(), InstType.PROD_INST_STATE)
        .put(TableConsts.SubProdInst.getTableName(), InstType.SUB_PROD_INST)
        .build();

    /**
     * 组装订单费用
     *
     * @deprecated 废弃，请使用新处理逻辑dealAcctItem
     * @param request
     */
    @Deprecated
    public static void dealFeeInfo(OrderRequest request) {
        // 订单项对应费用项
        Map<String, List<AcctItemHis>> orderItemAcctItemMap = Maps.newHashMap();
        // 记录费用项对应订单项
        Map<String, List<OrderItem>> acctItemOrderMap = Maps.newHashMap();
        Map<String, ShoppingCartItemFeeDTO> cartItemFeeMap = Maps.newHashMap();

        for (OrderItem orderItem : request.getOrderContainer().getOrderItemMap().values()) {
            String orderItemId = orderItem.getOrderItemId();

            // 获取订单项匹配的符合条件购物车费用项
            List<ShoppingCartItemFeeDTO> shoppingCartItemFeeList = getCartItemFeeByOrderItem(request, orderItem);

            if (CollectionUtils.isNotEmpty(shoppingCartItemFeeList)) {
                List<AcctItemHis> acctItems = Lists.newArrayList();
                for (ShoppingCartItemFeeDTO shoppingCartItemFee : shoppingCartItemFeeList) {
                    cartItemFeeMap.put(shoppingCartItemFee.getShoppingCartItemFeeId(), shoppingCartItemFee);
                    // 费用项去重
                    boolean flag = acctItems.stream().anyMatch(
                        p -> KiteStringUtils.equals(shoppingCartItemFee.getShoppingCartItemFeeId(), p.getAcctItemId()));

                    if (flag) {
                        continue;
                    }
                    // 根据订单变动信息匹配费用项
                    if (matchFeeItem(request, orderItem, shoppingCartItemFee)) {
                        AcctItemHis acctItem = createAcctItemHis(request, orderItem, shoppingCartItemFee);
                        acctItems.add(acctItem);
                        orderItemAcctItemMap.computeIfAbsent(orderItemId, key -> Lists.newArrayList()).add(acctItem);
                        acctItemOrderMap.computeIfAbsent(acctItem.getAcctItemId(), key -> Lists.newArrayList())
                            .add(orderItem);
                    }
                }

            }
        }

        // 费用去重处理
        distinctAcctItem(request, orderItemAcctItemMap, acctItemOrderMap, cartItemFeeMap);
        request.getOrderContainer().getAcctItemMap().putAll(orderItemAcctItemMap);
    }

    /**
     * Description: <br>
     * 组装订单费用项
     *
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @param request <br>
     */
    public static void dealAcctItem(OrderRequest request) {
        Set<Entry<String, List<ShoppingCartItemFeeDTO>>> shoppingCartItemFeeSet = request.getGroupInstContainer()
            .getShoppingCartItemFeeMap().entrySet();
        for (Entry<String, List<ShoppingCartItemFeeDTO>> entry : shoppingCartItemFeeSet) {
            List<ShoppingCartItemFeeDTO> shoppingCartItemFees = entry.getValue();

            // 遍历所有购物车费用项
            for (ShoppingCartItemFeeDTO shoppingCartItemFee : shoppingCartItemFees) {

                // 根据购物车订单费用获取符合订单项
                List<OrderItem> orderItems = listOrderItemsByShoppingCartItemFee(request, shoppingCartItemFee);
                if (KiteListUtils.isEmpty(orderItems)) {
                    // 不需要校验购物车费用项是否匹配有效订单项
                    if (GeneralSwitchUtils.isSwitchOpened(SwitchConsts.SHOP_CART_ITEM_FEE_NO_CHECK)) {
                        continue;
                    }
                    else {
                        // 购物车费用项[{0}]没有匹配有效的订单项，请检查购物车费用项数据！
                        ErrorConsts.SHOPPING_CART_ITEM_FEE_MATCH_ORDER_ITEM
                            .throwOut(shoppingCartItemFee.getShoppingCartItemFeeId());
                    }
                }

                // 获取优先级高的订单项
                OrderItem orderItem = getHighPriorityOrderItem(request, shoppingCartItemFee, orderItems);
                // 生成费用项
                AcctItemHis acctItem = createAcctItemHis(request, orderItem, shoppingCartItemFee);

                // 添加费用项
                request.getOrderContainer().getAcctItemMap()
                    .computeIfAbsent(orderItem.getOrderItemId(), key -> Lists.newArrayList()).add(acctItem);
            }
        }
    }

    /**
     * Description: <br>
     * 获取优先级高的订单项 <br>
     * 1.优先根据订单实例变动匹配 <br>
     * 2.根据服务提供匹配
     *
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @param shoppingCartItemFee
     * @param orderItems
     * @return <br>
     */
    public static OrderItem getHighPriorityOrderItem(OrderRequest request, ShoppingCartItemFeeDTO shoppingCartItemFee,
        List<OrderItem> orderItems) {
        OrderItem retOrderItem = null;
        List<OrderItem> matchOrderItems = Lists.newArrayList();
        for (OrderItem orderItem : orderItems) {
            // 优先根据订单实例变动匹配
            if (matchFeeItem(request, orderItem, shoppingCartItemFee)) {
                matchOrderItems.add(orderItem);
            }
        }

        if (!KiteListUtils.isEmpty(matchOrderItems)) {
            // 匹配服务提供
            retOrderItem = matchOrderItems.stream()
                .filter(p -> KiteStringUtils.equals(p.getServiceOfferId(), shoppingCartItemFee.getServiceOfferId()))
                .findFirst().orElse(matchOrderItems.get(0));
        }
        else {
            // 匹配服务提供
            retOrderItem = orderItems.stream()
                .filter(p -> KiteStringUtils.equals(p.getServiceOfferId(), shoppingCartItemFee.getServiceOfferId()))
                .findFirst().orElse(orderItems.get(0));
        }

        return retOrderItem;
    }

    /**
     * Description: <br>
     * 根据购物车订单费用获取符合订单项集合
     *
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @param request
     * @param key
     * @param orderItem
     * @return <br>
     */
    public static List<OrderItem> listOrderItemsByShoppingCartItemFee(OrderRequest request,
        ShoppingCartItemFeeDTO shoppingCartItemFee) {
        List<OrderItem> retOrderItems = Lists.newArrayList();

        List<OrderItem> allOrderItems = OrderContainer.ofRequest(request).listOrderItems();
        for (OrderItem orderItem : allOrderItems) {
            String offerType = orderItem.getOfferKind();
            // 获取基础销售品匹配费用
            if (KiteStringUtils.isEqual(offerType, KeyValues.OFFER_KIND_0)) {
                if (matchBaseOffeOrderItemFee(request, orderItem, shoppingCartItemFee)) {
                    retOrderItems.add(orderItem);
                }
            }
            else {
                // 获取套餐匹配销售品费用
                if (matchOffeOrderItemFee(request, orderItem, shoppingCartItemFee)) {
                    retOrderItems.add(orderItem);
                }
            }
        }

        return retOrderItems;
    }


    /**
     * Description: <br>
     * 根据实例类型和实例ID匹配购物车费用项
     *
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @param shoppingCartItemFee
     * @param instType
     * @param instId
     * @return <br>
     */
    public static boolean matchCartItemFeeByInst(ShoppingCartItemFeeDTO shoppingCartItemFee, InstType instType,
        String instId) {
        String cartItemFeeKey = ManagerUtils.join(shoppingCartItemFee.getCartItemCd(), shoppingCartItemFee.getObjId());
        String curkey = ManagerUtils.join(instTypeCartItemCdMapping.get(instType), instId);

        if (KiteStringUtils.isEqual(cartItemFeeKey, curkey)) {
            return Boolean.TRUE;
        }

        return Boolean.FALSE;
    }

    /**
     * Description: <br>
     * 根据变动信息匹配费用项
     *
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @param request
     * @param orderItem
     * @param shoppingCartItemFee
     * @return <br>
     */
    public static boolean matchCartItemFeeByOrderItemChange(OrderRequest request, OrderItem orderItem,
        ShoppingCartItemFeeDTO shoppingCartItemFee) {

        List<OrderItemChange> orderItemChanges = OrderContainer.ofRequest(request)
            .listOrderItemChangesByOrderItemId(orderItem.getOrderItemId());

        for (OrderItemChange orderItemChange : orderItemChanges) {
            String tableName = orderItemChange.getTableName();
            String instId = orderItemChange.getInstId();

            InstType instType = tableNameInstTypeMappinst.get(tableName);
            if (!Objects.isNull(instType)) {
                if (matchCartItemFeeByInst(shoppingCartItemFee, instType, instId)) {
                    return Boolean.TRUE;
                }
            }

            // 销售品实例匹配
            if (KiteStringUtils.isEqual(tableName, TableConsts.OfferInst.getTableName())) {
                for (InstType offerInstType : offerType2InstType.values()) {
                    if (matchCartItemFeeByInst(shoppingCartItemFee, offerInstType, instId)) {
                        return Boolean.TRUE;
                    }
                }
            }
        }

        // 上述都没有匹配到，则可能实例产生费用挂在父销售品实例上(产品实例或者销售品实例ID)
        // 获取上级销售品实例
        String parentInstId = getParentInstId(request, orderItem);
        if (matchCartItemFeeByInst(shoppingCartItemFee, offerType2InstType.get(orderItem.getOfferKind()),
            parentInstId)) {
            return Boolean.TRUE;
        }

        return Boolean.FALSE;
    }

    /**
     * Description: <br>
     * 获取父实例ID
     *
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @param request
     * @param orderItem
     * @return <br>
     */
    public static String getParentInstId(OrderRequest orderRequest, OrderItem orderItem) {
        String instId = "";
        String objId = orderItem.getObjId();

        if (KiteStringUtils.equals(KeyConsts.OFFER_TYPE_10, orderItem.getOfferKind())) {
            ProdInstMapper prodInstMapper = SpringUtil.getBean(ProdInstMapper.class);
            ProdInst prodInst = prodInstMapper.getProdInstIdByCompInstId(orderItem.getObjId(), null);
            if (Objects.nonNull(prodInst)) {
                instId = prodInst.getProdInstId();
            }
        }
        else {
            String tableName = TableConsts.OfferInst.getTableName();
            OfferInst parentInst = (OfferInst) InstLoaderFactory.getInstLoader(tableName).loadInst(orderRequest,
                tableName, objId, orderRequest.getCustId());
            instId = parentInst.getOfferInstId();
        }

        return instId;
    }

    /**
     * Description: <br>
     * 基础销售品费用项匹配
     *
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @return <br>
     */
    public static boolean matchBaseOffeOrderItemFee(OrderRequest request, OrderItem orderItem,
        ShoppingCartItemFeeDTO shoppingCartItemFee) {

        // 获取接入产品实例
        ProdInst prodInst = request.getInstContainer().getProdInstMap().get(orderItem.getObjId());
        if (!Objects.isNull(prodInst)) {
            // 匹配接入产品实例费用
            if (matchCartItemFeeByInst(shoppingCartItemFee, InstType.PROD_INST, prodInst.getProdInstId())) {
                return Boolean.TRUE;
            }

            // 匹配功能产品实例费用
            List<ProdInstFunc> prodInstFuncs = InstContainer.ofRequest(request)
                .listProdInstFuncs(prodInst.getProdInstId());
            for (ProdInstFunc prodInstFunc : prodInstFuncs) {
                if (matchCartItemFeeByInst(shoppingCartItemFee, InstType.PROD_INST_FUNC,
                    prodInstFunc.getProdInstId())) {
                    return Boolean.TRUE;
                }
            }

            // 匹配终端实例费用
            List<OfferResInstRelExt> offerResInstRelExts = InstContainer.ofRequest(request)
                .listOfferResInstRelExts(prodInst.getCompInstId());
            for (OfferResInstRelExt offerResInstRelExt : offerResInstRelExts) {
                if (matchCartItemFeeByInst(shoppingCartItemFee, InstType.MKT_RES_INST,
                    offerResInstRelExt.getOfferResInstRelId())) {
                    return Boolean.TRUE;
                }
            }

            // 匹配产品可选包费用
            List<OfferInst> offerInsts = InstContainer.ofRequest(request)
                .listAdditionalOfferInsts(prodInst.getCompInstId());
            for (OfferInst offerInst : offerInsts) {
                if (matchCartItemFeeByInst(shoppingCartItemFee, InstType.ADDITIONAL_OFFER_INST,
                    offerInst.getOfferInstId())) {
                    return Boolean.TRUE;
                }
            }
        }

        if (matchCartItemFeeByOrderItemChange(request, orderItem, shoppingCartItemFee)) {
            return Boolean.TRUE;
        }

        return Boolean.FALSE;
    }

    /**
     * Description: <br>
     * 套餐销售品费用项匹配
     *
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @return <br>
     */
    public static boolean matchOffeOrderItemFee(OrderRequest request, OrderItem orderItem,
        ShoppingCartItemFeeDTO shoppingCartItemFee) {
        // 获取销售品实例
        OfferInst offerInst = request.getInstContainer().getOfferInstMap().get(orderItem.getObjId());
        if (Objects.isNull(offerInst)) {
            return Boolean.FALSE;
        }

        // 匹配销售品实例费用
        if (matchCartItemFeeByInst(shoppingCartItemFee, offerType2InstType.get(offerInst.getOfferType()),
            offerInst.getOfferInstId())) {
            return Boolean.TRUE;
        }

        // 获取包内可选包费用
        List<OfferInst> offerInsts = InstContainer.ofRequest(request)
            .listAdditionalOfferInsts(offerInst.getCompInstId());
        for (OfferInst inst : offerInsts) {

            if (matchCartItemFeeByInst(shoppingCartItemFee, InstType.ADDITIONAL_OFFER_INST, inst.getOfferInstId())) {
                return Boolean.TRUE;
            }
        }

        if (matchCartItemFeeByOrderItemChange(request, orderItem, shoppingCartItemFee)) {
            return Boolean.TRUE;
        }

        return Boolean.FALSE;
    }

    /**
     *
     * Description: <br>
     *  费用去重处理
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @param request
     * @param orderItemAcctItemMap
     * @param acctItemOrderMap
     * @param cartItemFeeMap <br>
     */
    public static void distinctAcctItem(OrderRequest request, Map<String, List<AcctItemHis>> orderItemAcctItemMap,
        Map<String, List<OrderItem>> acctItemOrderMap, Map<String, ShoppingCartItemFeeDTO> cartItemFeeMap) {
        for (Entry<String, List<OrderItem>> acctItemEntry : acctItemOrderMap.entrySet()) {
            String acctItemId = acctItemEntry.getKey();
            List<OrderItem> orderItems = acctItemEntry.getValue();
            if (KiteListUtils.isEmpty(orderItems)) {
                continue;
            }

            if (orderItems.size() > 1) {
                ShoppingCartItemFeeDTO cartItemFee = cartItemFeeMap.get(acctItemId);
                // 一笔费用项对应多个订单项,优先匹配服务提供
                OrderItem fixOrderItem = orderItems.stream()
                    .filter(p -> KiteStringUtils.equals(p.getServiceOfferId(), cartItemFee.getServiceOfferId()))
                    .findFirst().orElse(orderItems.get(0));

                // 排除其他订单项
                for (OrderItem orderItem : orderItems) {
                    if (!KiteStringUtils.isEqual(orderItem.getOrderItemId(), fixOrderItem.getOrderItemId())) {
                        // 去掉重复费用项
                        orderItemAcctItemMap.getOrDefault(orderItem.getOrderItemId(), Lists.newArrayList())
                            .removeIf(p -> KiteStringUtils.isEqual(acctItemId, p.getAcctItemId()));
                    }
                }
            }

        }
    }

    /**
     * Description: <br>
     * 获取订单项对应购物车费用项
     *
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @param request
     * @param orderItem
     * @return <br>
     */
    public static List<ShoppingCartItemFeeDTO> getCartItemFeeByOrderItem(OrderRequest request, OrderItem orderItem) {
        List<ShoppingCartItemFeeDTO> shoppingCartItemFeeList = Lists.newArrayList();
        String offerType = orderItem.getOfferKind();
        // 获取基础销售品匹配费用
        if (KiteStringUtils.isEqual(offerType, KeyValues.OFFER_KIND_0)) {
            shoppingCartItemFeeList.addAll(getCartItemFeeByProdOrderItem(request, orderItem));
        }
        else {
            // 获取套餐匹配销售品费用
            shoppingCartItemFeeList.addAll(getCartItemFeeByOfferOrderItem(request, orderItem));
        }

        return shoppingCartItemFeeList;
    }

    /**
     * Description: <br>
     * 根据实例对象类型和实例ID获取费用项
     *
     * @taskId <br>
     * @param request
     * @param instType
     * @param instId
     * @return <br>
     */
    public static List<ShoppingCartItemFeeDTO> getCartItemFeesByKey(OrderRequest request, InstType instType,
        String instId) {
        String key = ManagerUtils.join(instTypeCartItemCdMapping.get(instType), instId);
        return Optional.ofNullable(request.getGroupInstContainer().getShoppingCartItemFeeMap().get(key))
            .orElse(Lists.newArrayList());
    }

    /**
     * Description: <br>
     * 获取基础销售品费用
     *
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @return <br>
     */
    public static List<ShoppingCartItemFeeDTO> getCartItemFeeByProdOrderItem(OrderRequest request,
        OrderItem orderItem) {
        List<ShoppingCartItemFeeDTO> cartItemFeeList = Lists.newArrayList();

        // 获取接入产品实例
        ProdInst prodInst = request.getInstContainer().getProdInstMap().get(orderItem.getObjId());
        if (Objects.isNull(prodInst)) {
            return cartItemFeeList;
        }
        // 获取接入产品实例费用
        cartItemFeeList.addAll(getCartItemFeesByKey(request, InstType.PROD_INST, prodInst.getProdInstId()));

        // 获取功能产品实例费用
        List<ProdInstFunc> prodInstFuncs = InstContainer.ofRequest(request).listProdInstFuncs(prodInst.getProdInstId());
        for (ProdInstFunc prodInstFunc : prodInstFuncs) {
            cartItemFeeList.addAll(getCartItemFeesByKey(request, InstType.PROD_INST_FUNC, prodInstFunc.getProdInstId()));
        }

        // 获取终端实例费用
        List<OfferResInstRelExt> offerResInstRelExts = InstContainer.ofRequest(request).listOfferResInstRelExts(prodInst.getCompInstId());
        for (OfferResInstRelExt offerResInstRelExt : offerResInstRelExts) {
            cartItemFeeList.addAll(getCartItemFeesByKey(request, InstType.MKT_RES_INST, offerResInstRelExt.getOfferResInstRelId()));
        }

        // 获取产品可选包费用
        List<OfferInst> offerInsts = InstContainer.ofRequest(request).listAdditionalOfferInsts(prodInst.getCompInstId());
        for (OfferInst offerInst : offerInsts) {
            cartItemFeeList.addAll(getCartItemFeesByKey(request, InstType.ADDITIONAL_OFFER_INST, offerInst.getOfferInstId()));
        }

        return cartItemFeeList;
    }


    /**
     * Description: <br>
     * 获取套餐销售品费用
     *
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @return <br>
     */
    public static List<ShoppingCartItemFeeDTO> getCartItemFeeByOfferOrderItem(OrderRequest request,
        OrderItem orderItem) {
        List<ShoppingCartItemFeeDTO> cartItemFeeList = Lists.newArrayList();
        // 获取销售品实例
        OfferInst offerInst = request.getInstContainer().getOfferInstMap().get(orderItem.getObjId());
        if (Objects.isNull(offerInst)) {
            return cartItemFeeList;
        }

        // 获取销售品实例费用
        cartItemFeeList.addAll(getCartItemFeesByKey(request, offerType2InstType.get(offerInst.getOfferType()), offerInst.getOfferInstId()));

        // 获取包内可选包费用
        List<OfferInst> offerInsts = InstContainer.ofRequest(request).listAdditionalOfferInsts(offerInst.getCompInstId());
        for (OfferInst inst : offerInsts) {
            cartItemFeeList.addAll(getCartItemFeesByKey(request, InstType.ADDITIONAL_OFFER_INST, inst.getOfferInstId()));
        }

        return cartItemFeeList;
    }

    /**
     * Description: <br>
     * 根据变动信息匹配费用项
     *
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @param request
     * @param orderItem
     * @param shoppingCartItemFee
     * @return <br>
     */
    public static boolean matchFeeItem(OrderRequest request, OrderItem orderItem,
        ShoppingCartItemFeeDTO shoppingCartItemFee) {
        boolean flag = false;

        List<OrderItemChange> orderItemChanges = OrderContainer.ofRequest(request)
            .listOrderItemChangesByOrderItemId(orderItem.getOrderItemId());

        for (OrderItemChange orderItemChange : orderItemChanges) {
            if (KiteStringUtils.isEqual(shoppingCartItemFee.getObjId(), orderItemChange.getInstId())) {
                flag = true;
                break;
            }
        }
        return flag;
    }


    /**
     * Description: <br>
     * 生成费用项节点
     *
     * @param request
     * @param orderItem
     * @param shoppingCartItemFee
     * @return <br>
     */
    private static AcctItemHis createAcctItemHis(OrderRequest request, OrderItem orderItem,
        ShoppingCartItemFeeDTO shoppingCartItemFee) {
        AcctItemHis acctItem = KiteBeanUtils.transform(shoppingCartItemFee, AcctItemHis.class);
        acctItem.setAcctItemId(shoppingCartItemFee.getShoppingCartItemFeeId());
        acctItem.setAcceptDate(orderItem.getAcceptDate());
        acctItem.setCreatedDate(orderItem.getCreateDate());
        acctItem.setState(shoppingCartItemFee.getStatusCd());
        acctItem.setStateDate(request.getAcceptDate());
        acctItem.setStaffId(shoppingCartItemFee.getCreateStaff());
        acctItem.setBillLanId(orderItem.getAcceptLanId());
        acctItem.setOfferCompId(orderItem.getApplyObjSpec());
        acctItem.setServiceOfferId(orderItem.getServiceOfferId());
        acctItem.setCustOrderId(orderItem.getCustOrderId());
        acctItem.setCustId(orderItem.getBelongCustId());
        acctItem.setUndoFlag(Objects.equals("F", orderItem.getUndoFlag()) ? "0" : "1");
        // 设置用户业务号码，如果为空获取任意套餐下一个成员号码(TODO)
        acctItem.setProdNo(orderItem.getAccNbr());
        acctItem.setOfferInstId(orderItem.getObjId());
        acctItem.setOrderItemId(orderItem.getOrderItemId());
        acctItem.setOldOrderItemId(orderItem.getOldOrderItemId());
        acctItem.setLanId(orderItem.getAcceptLanId());
        acctItem.setBusinessId(orderItem.getAcceptRegionId());
        acctItem.setStatusDate(request.getAcceptDate());
        acctItem.setExtAcctItemId(shoppingCartItemFee.getShoppingCartItemFeeId());
        acctItem.setStateDate(orderItem.getCreateDate());
        acctItem.setPayedDate(orderItem.getCreateDate());
        acctItem.setBillStaffId(request.getStaffId());
        acctItem.setBillTeamId(request.getOrgId());
        acctItem.setBillBusinessId(request.getRegionId());
        acctItem.setTeamId(request.getOrderContainer().getCustomerOrder().getCreateOrgId());
        acctItem.setApveAmount(shoppingCartItemFee.getAdjustAmount());
        acctItem.setPricingDetailId("-1");
        acctItem.setInvoiceId(shoppingCartItemFee.getInvoiceId());
        acctItem.setResInstId("-1");
        acctItem.setInvoiceItemId("-1");
        acctItem.setPrefOffInstId(KiteStringUtils.isEmpty(shoppingCartItemFee.getOwnerInstId()) ? "-1"
            : shoppingCartItemFee.getOwnerInstId());
        acctItem.setFeeProp("0");
        acctItem.setStatusCd("");

        fillNullProdNo(acctItem, request);

        return acctItem;
    }

    private static void fillNullProdNo(AcctItemHis acctItem, OrderRequest request) throws BssException {
        if (StringUtils.isNotEmpty(acctItem.getProdNo())) {
           return;
        }
        StringBuilder prodNo = new StringBuilder();
        String prefOffInstId = acctItem.getPrefOffInstId();
        if (prefOffInstId == null || "-1".equals(prefOffInstId) || "".equals(prefOffInstId)) {
            prefOffInstId = acctItem.getOfferInstId();
        }

        Collection<OfferObjInstRel> fillNullProdNoList =
                request.getInstContainer().getOfferObjInstRelMap().get(acctItem.getOfferInstId()).values();
        if (CollectionUtils.isEmpty(fillNullProdNoList)) {
            return;
        }

        for (OfferObjInstRel offerObjInstRel : fillNullProdNoList) {
            String obj_type = offerObjInstRel.getObjType();
            if (CoreDataOffer.OFF_C_0044_100000.equals(obj_type)) {
                //产品级别成员
                Collection<ProdInst> prodInstList = request.getInstContainer().getProdInstMap().values();
                prodNo.append(CollectionUtils.isNotEmpty(prodInstList) ? new ArrayList<ProdInst>(prodInstList).get(0).getAccNum() : "");
//                acctItem.setProdNo(prod);
            }
            else if (KiteStringUtils.equals(CoreDataOffer.OFF_C_0044_170000, obj_type)) {
                //账户级别成员；
                IQueryAccountService iQueryAccountService = SpringUtil.getBean(IQueryAccountService.class);
                PageInfo<AccountDTO> resultObj = iQueryAccountService.listAccounts(request.getCustId(), AccountSearchType.T1.name(), request.getCustId(), 1, 10);
                List<AccountDTO> accountList = resultObj.getList();

                IQuerySceneInstService iQuerySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
                for (Iterator<AccountDTO> item = accountList.iterator(); item.hasNext();) {
                    String prodInstId = item.next().getProdInstId();
                    KiteProdInst prodInst = iQuerySceneInstService.getProdInst(request.getCustId(), prodInstId);
                    prodNo.append(prodInst.getAccNum());
                    if (item.hasNext()) {
                        prodNo.append(",");
                    }
                }
            }
        }
        acctItem.setProdNo(prodNo.toString());
    }
}
